package com.example.synccenter.task;

import com.example.synccenter.identitysource.core.IdentitySource;
import com.example.synccenter.identitysource.core.IdentitySourceConfig;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.util.StopWatch;

import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * 身份源同步定时任务，负责定时执行身份源数据同步。
 * 使用分布式锁确保在分布式环境下同一时间只有一个节点在执行同步。
 */
@Slf4j
@RequiredArgsConstructor
public class IdentitySourceSyncTask implements Runnable {
    private static final String LOCK_PREFIX = "identity_source_sync:";

    /**
     * 身份源ID
     */
    private final String id;

    /**
     * 身份源名称
     */
    private final String name;

    /**
     * Redis分布式锁客户端
     */
    private final RedissonClient redissonClient;

    /**
     * 身份源实例
     */
    private final IdentitySource<? extends IdentitySourceConfig> identitySource;

    /**
     * 执行同步任务
     * 1. 使用分布式锁确保同一时间只有一个节点在执行同步
     * 2. 记录任务执行时间
     * 3. 处理同步异常并释放锁
     */
    @Override
    public void run() {
        StopWatch stopWatch = new StopWatch();
        stopWatch.start();
        log.info("[任务触发]-同步身份源[{}]数据开始", name);

        RLock lock = redissonClient.getLock(LOCK_PREFIX + id);
        boolean locked = false;
        try {
            locked = lock.tryLock(1, TimeUnit.SECONDS);
            if (locked) {
                identitySource.sync(Map.of("triggerType", "SCHEDULED"));
            } else {
                log.warn("获取同步锁失败，跳过本次同步: {}", name);
            }
        } catch (Exception e) {
            log.error("同步身份源数据失败: {}, 错误: {}", name, e.getMessage(), e);
        } finally {
            if (locked && lock.isLocked()) {
                lock.unlock();
            }
            stopWatch.stop();
            log.info("[任务触发]-同步身份源[{}]数据结束, 执行时长: {} ms", name, stopWatch.getTotalTimeMillis());
        }
    }
} 